package com.piece.module.file.util.pdf;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.io.util.StreamUtil;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.CompressionConstants;
import com.itextpdf.kernel.pdf.EncryptionConstants;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.font.FontSet;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.module.file.util.convert.ChineseSplitCharacters;
import com.piece.module.file.util.pdf.event.FooterIEvent;
import com.piece.module.file.util.pdf.event.HeaderIEvent;
import com.piece.module.file.util.pdf.event.WaterMarIEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * Pdf构建器
 */
@Slf4j
public abstract class AbstractPdfBuilder implements IPdfBuilder {

    protected PdfDocument pdf;
    protected Document doc;
    protected PdfFont font;
    protected PdfFont waterFont;
    protected ConverterProperties proper;
    protected Properties properties = new Properties();
    protected BuilderContext builderContext;
    protected Object model;
    protected HeaderIEvent headerIEvent;
    protected FooterIEvent footerIEvent;
    protected WaterMarIEvent waterMarIEvent;

    public BuilderContext getBuilderContext() {
        return builderContext;
    }

    public AbstractPdfBuilder(BuilderContext builderContext) {
        this.builderContext = builderContext;
        initPdf();
    }

    public void setModel(Object model) {
        this.model = model;
    }

    public void setPdfDocument(PdfDocument pdf) {
        this.pdf = pdf;
    }

    public void setHeaderIEvent(HeaderIEvent headerIEvent) {
        this.headerIEvent = headerIEvent;
    }

    public void setFooterIEvent(FooterIEvent footerIEvent) {
        this.footerIEvent = footerIEvent;
    }

    public void initPdf() {
        // 压缩文字
        WriterProperties writerProperties = new WriterProperties();
        writerProperties.setCompressionLevel(CompressionConstants.BEST_COMPRESSION);
        writerProperties.setFullCompressionMode(true);

        // Pdf加密
        String pwd = builderContext.getPdfPassword();
        if (StringUtil.isNotEmpty(pwd)) {
            writerProperties.setStandardEncryption(pwd.getBytes(), pwd.getBytes(), EncryptionConstants.ALLOW_PRINTING,
                    EncryptionConstants.ENCRYPTION_AES_128 | EncryptionConstants.DO_NOT_ENCRYPT_METADATA);
        }

        pdf.setDefaultPageSize(PageSize.A4);
        pdf.getDefaultPageSize().applyMargins(0, 0, 0, 0, true);

        FontProvider fontProvider = null;
        try {
            // 获取项目路径
            Properties props = System.getProperties();
            String rootPath = props.getProperty("user.dir");
            InputStream inputStream = PdfUtil.class.getClassLoader().getResourceAsStream(builderContext.getFontPath());
            File upload = new File(rootPath, "upload/font");
            if (!upload.exists()) {
                upload.mkdirs();
            }
            upload = new File(rootPath, "upload" + File.separator + builderContext.getFontPath());
            if (!upload.exists()) {
                upload.createNewFile();
                FileUtils.writeByteArrayToFile(upload, StreamUtil.inputStreamToArray(inputStream));
            }

            //font = PdfFontFactory.createFont(upload.getPath(), PdfEncodings.UTF8);
            //waterFont = PdfFontFactory.createFont(upload.getPath() , PdfEncodings.UTF8);
            font = PdfFontFactory.createFont("STSong-Light","UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.FORCE_NOT_EMBEDDED);
            waterFont = PdfFontFactory.createFont("STSong-Light","UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.FORCE_NOT_EMBEDDED);

            // 字体设置，解决中文不显示问题
            FontSet fontSet = new FontSet();
            //fontSet.addFont(upload.getPath() + ",0", PdfEncodings.UTF8);
            fontSet.addFont("STSong-Light","UniGB-UCS2-H");
            fontProvider = new FontProvider(fontSet);
        } catch (IOException e) {
            log.error("获取pdf字体出错", e.getMessage());
        }

        doc = new Document(pdf);
        doc.setMargins(50, 60, 60, 60);
        doc.setFont(font);
        doc.setFontSize(10f);
        doc.setCharacterSpacing(0.1f);

        // 中文标点行首问题
        ChineseSplitCharacters chineseSplitCharacters = new ChineseSplitCharacters();
        doc.setSplitCharacters(chineseSplitCharacters);

        proper = new ConverterProperties();
        proper.setFontProvider(fontProvider);
    }

    /**
     * 一键构建
     */
    public IPdfBuilder buildAll(Object data) {
        this.model = data;
        addIndex();
        // 添加响应事件
        addWaterMarEvent();
        addHeaderEvent();
        addFooterEvent();
        addContext();
        addBackCover();
        // 关闭响应事件
        closeEvent();
        build();
        return this;
    }

    /**
     * 添加首页
     */
    @Override
    public abstract IPdfBuilder addIndex();

    /**
     * 添加页眉响应
     */
    public void addHeaderEvent() {
        if (null != headerIEvent && builderContext.isShowHeader()) {
            pdf.addEventHandler(PdfDocumentEvent.START_PAGE, headerIEvent);
        }
    }

    /**
     * 添加页脚响应
     */
    public void addFooterEvent() {
        if (null != footerIEvent && builderContext.isShowFooter()) {
            pdf.addEventHandler(PdfDocumentEvent.START_PAGE, footerIEvent);
        }
    }

    /**
     * 添加水印响应
     */
    public void addWaterMarEvent() {
        if (null != waterMarIEvent && (StringUtil.isNotEmpty(builderContext.getWaterMark()) || null != builderContext.getBackground())) {
            pdf.addEventHandler(PdfDocumentEvent.START_PAGE, waterMarIEvent);
        }
    }

    public void closeEvent() {
        if (null != headerIEvent) {
            pdf.removeEventHandler(PdfDocumentEvent.START_PAGE, headerIEvent);
        }
        if (null != footerIEvent) {
            pdf.removeEventHandler(PdfDocumentEvent.START_PAGE, footerIEvent);
        }
        if (null != waterMarIEvent) {
            pdf.removeEventHandler(PdfDocumentEvent.START_PAGE, waterMarIEvent);
        }
    }

    public void build() {
        pdf.close();
    }

    /**
     * 添加正文
     */
    @Override
    public abstract IPdfBuilder addContext();

    /**
     * 封底
     */
    @Override
    public abstract IPdfBuilder addBackCover();
}
